<?php

function is_associative_array($array){
	return is_array($array)
		&& !empty($array)
		&& (array_keys($array) !== range(0, count($array) - 1));
}

function is_enumerative_array($array){
	return is_array($array) && !is_associative_array($array);
}

function starts_with($string, $prefix) {
	return substr($string, 0, strlen($prefix))===$prefix;
}

/**
 * Splits array into two arrays using a callback function
 *
 * It is like array_filter(), but instead of one array, two arrays are returned:
 * first one with elements for which the callback function evaluates to true,
 * and second one, for which it evaluates to false.
 *
 * If no callback is supplied, all entries of input equal to FALSE will be removed.
 *
 * Array keys are preserved.
 *
 * @param $callback the callback function to use
 * @return array(truth_array, false_array)
 */
function array_split($input, $callback=null) {
    $callback = isset($callback) ? $callback : create_function('$x', 'return $x == true;');
    
    $true = array();
    $false = array();
    foreach ($input as $key => $value) {
        if (call_user_func($callback, $value)) {
            $true[$key] = $value;
        }
        else {
            $false[$key] = $value;
        }
    }
    
    return array($true, $false);
}

function assertUserInput($condition, $message='invalid user input') {
	if(!$condition) {
		throw new Exception($message);
	}
}

function array_of_objects_intersect() {
	if(func_num_args()==0) {
		trigger_error(__FUNCTION__ .' needs one or more array arguments', E_USER_WARNING);
	} elseif(func_num_args()==1) {
		return func_get_arg(0);
	} else {
		$arrays=array();
		foreach(func_get_args() as $array) {
			$arrays[]=array_map('serialize', $array);		
		}
		return array_values(
			array_map(
				'unserialize', 
				call_user_func_array('array_intersect', $arrays)
			)
		);
	}
}

function object_ksort($object) {
	$vars=get_object_vars($object);
	ksort($vars);
	foreach($vars as $name=>$value) {
		unset($object->$name);
	}
	foreach($vars as $name=>$value) {
		$object->$name=$value;
	}
}

function array_of_objects_diff($a, $b) {

	if(func_num_args()==0) {
		trigger_error(__FUNCTION__ .' needs one or more array arguments', E_USER_WARNING);
	} elseif(func_num_args()==1) {
		return func_get_arg(0);
	} else {
		$arrays=array();
		foreach(func_get_args() as $array) {
			$arrays[]=array_map('serialize', $array);		
		}
		return array_values(
			array_map(
				'unserialize', 
				call_user_func_array('array_diff', $arrays)
			)
		);
	}
}

function random_string($length=16, $options='ABCDEFGHIGKLMNOPQRSTUVXYZ') {
	$result='';
	for($i=0; $i<$length; $i++) {
		$result.=$options[rand(0, strlen($options)-1)];
	}
	return $result;
}

function is_safe_name($string) {
	return preg_match('/^[_A-Za-z][_A-Za-z0-9]+$/', $string) ? true : false;
}

function object_merge($obj1, $obj2) {
	$result=new Object();
	foreach(func_get_args() as $object) {
		foreach($object as $attr=>$value) {
			$result->$attr=$value;
		}
	}
	return $result;
}

function array_get_values($array, $keys) {
	$result=array();
	foreach($array as $key=>$value) {
		if(in_array($key, $keys)) {
			$result[]=$value;
		}
	}
	return $array();
}

function ltrim_path($path) {
	return ltrim($path, " /\t\n\r\0\x0B");
}

function parse_path($path) {
	if(!$path) { // none results, of course, in (none, none)
		return array(null, null);		
	}	
	if(!is_string($path)) {
		throw new Exception('url must be string, '.gettype($path).' found');
	}
	$path=ltrim_path($path);
	$pos=strpos($path, '/');
	if($pos!==false) {
		return array(
			urldecode(substr($path, 0, $pos)),
			substr($path, $pos)
		);
	} else {
		return array(urldecode($path), null);
	}
	
	return;
}

function join_path() {
	$parts=array();
	foreach(func_get_args() as $arg) {
		$parts=trim($arg, "/ \t\n\r\0\x0B");	
	}
	return implode('/', $parts);
}

function array_merge_recursive_simple() {

    if (func_num_args() < 2) {
        trigger_error(__FUNCTION__ .' needs two or more array arguments', E_USER_WARNING);
        return;
    }
    $arrays = func_get_args();
    $merged = array();
    while ($arrays) {
        $array = array_shift($arrays);
        if (!is_array($array)) {
            trigger_error(__FUNCTION__ .' encountered a non array argument', E_USER_WARNING);
            return;
        }
        if (!$array)
            continue;
        foreach ($array as $key => $value)
            if (is_string($key))
                if (is_array($value) && array_key_exists($key, $merged) && is_array($merged[$key]))
                    $merged[$key] = call_user_func(__FUNCTION__, $merged[$key], $value);
                else
                    $merged[$key] = $value;
            else
                $merged[] = $value;
    }
    return $merged;
}


?>
